package com.biz.primus.ms.member.dao.redis;

import com.biz.primus.base.redis.CrudRedisDao;
import com.biz.primus.base.redis.util.RedisUtil;
import com.biz.primus.model.member.enums.AddressTypes;
import com.biz.primus.ms.member.dao.ro.MemberAddressRo;
import org.codelogger.utils.CollectionUtils;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * @author jun.liu
 * @date 2017年10月23日
 * @reviewer
 * @see
 */
@Repository
public class MemberAddressRedisDao extends CrudRedisDao<MemberAddressRo, Long> {

    @Override
    public void save(MemberAddressRo ro)
    {
        updateAddressAliasMapping(ro.getId(), ro.getMemberId(), ro.getAddressType().getValue());
        super.save(ro);
    }

    /**
     * 用于新增或修改了收货地址时,重置同名标签收获地址时调用的方法
     * 现在的逻辑是：一个标签只对应一个收货地址,所以这里重置的同名标签的收货地址只有一个
     */
    public void saveRos(Iterable<MemberAddressRo> ros)
    {
        for (MemberAddressRo ro : ros) {
            this.save(ro);
        }
    }

    @Override
    public void delete(MemberAddressRo ro)
    {
        super.delete(ro);
        zrem(userMappingKey(ro.getMemberId()), RedisUtil.toByteArray(ro.getId()));
        zrem(userAddressAliasMappingKey(ro.getMemberId(), ro.getAddressType().getValue()), RedisUtil.toByteArray(ro.getId()));
    }

    /**
     * 方法说明:根据用户id寻找用户对应的收货地址ro数据
     *
     * @param userId
     * @return
     * @throws
     */
    public List<MemberAddressRo> findByUserId(Long userId)
    {
        Set<byte[]> zRange;
        List<Long> ids = new ArrayList<>();
        for (AddressTypes addressAlias : AddressTypes.values()) {
            zRange = zRange(userAddressAliasMappingKey(userId, addressAlias.getValue()), 0, -1);
            ids.addAll(bytesSet2LongList(zRange));
        }
        return findByIds(ids);
    }

    /**
     * 方法说明:根据用户id查询用于已经设置的收货地址总数
     *
     * @param userId
     * @return
     * @throws
     */
    public int findCountByUserId(Long userId)
    {
        Set<byte[]> zRange = zRange(userMappingKey(userId), 0, -1);
        return zRange.size();
    }

    /**
     * @param userId
     * @param aias
     * @return
     */
    public List<Long> findAddressIdByAlias(Long userId, Integer aias)
    {
        String key = userAddressAliasMappingKey(userId, aias);
        Set<byte[]> bytes = zRange(key, 0, -1);
        return super.bytesSet2LongList(bytes);
    }

    /**
     * @param userId
     * @param addressAlias
     * @return
     */
    public List<MemberAddressRo> findAddressByAddressAlias(Long userId, Integer addressAlias)
    {
        List<Long> ids = findAddressIdByAlias(userId, addressAlias);
        List<MemberAddressRo> ros = findByIds(ids);
        return ros;
    }


    /**
     * 方法说明:建立和用户的关联
     *
     * @param userId
     * @return
     * @throws
     */
    private String userMappingKey(Long userId) {
        return getKeyByParams("userId", userId);
    }

    private String userAddressAliasMappingKey(Long userId, Integer addressAlias)
    {
        return getKeyByParams("userId", userId, "addressAlias", addressAlias).toString();
    }

    private void updateAddressAliasMapping(Long id, Long userId, Integer alias)
    {
        String mappingKey = userAddressAliasMappingKey(userId, alias);
        List<MemberAddressRo> ros = findByUserId(userId);
        if (CollectionUtils.isNotEmpty(ros))
        {
            for (MemberAddressRo ro : ros)
            {
                if (Objects.equals(id, ro.getId()))
                {
                    zrem(userAddressAliasMappingKey(userId, ro.getAddressType().getValue()), id + "");
                }
            }
        }
        zadd(mappingKey, System.currentTimeMillis(), RedisUtil.toByteArray(id));
    }
}